package cn.javaex.hgo.action.system.service.hgo_user_info;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.ConcurrentAccessException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.javaex.hgo.action.system.dao.hgo_menu_info.IHgoMenuInfoDAO;
import cn.javaex.hgo.action.system.dao.hgo_user_info.IHgoUserInfoDAO;
import cn.javaex.hgo.action.system.dao.hgo_user_role.IHgoUserRoleDAO;
import cn.javaex.hgo.action.system.service.hgo_menu_info.HgoMenuInfoService;
import cn.javaex.hgo.action.system.view.HgoMenuInfo;
import cn.javaex.hgo.action.system.view.HgoUserInfo;
import cn.javaex.hgo.config.constant.HgoErrorMsg;
import cn.javaex.hgo.config.exception.HgoException;

@Service("HgoUserInfoService")
public class HgoUserInfoService {
	
	@Autowired
	private IHgoUserInfoDAO iHgoUserInfoDAO;
	@Autowired
	private IHgoUserRoleDAO iHgoUserRoleDAO;
	@Autowired
	private IHgoMenuInfoDAO iHgoMenuInfoDAO;
	@Autowired
	private HgoMenuInfoService hgoMenuInfoService;
	
	/**
	 * 查询用户列表
	 * @param param
	 * @return
	 */
	public List<HgoUserInfo> list(Map<String, Object> param) {
		return iHgoUserInfoDAO.list(param);
	}

	/**
	 * 根据主键，查询用户信息
	 * @param id
	 * @return
	 */
	public HgoUserInfo selectById(String id) {
		return iHgoUserInfoDAO.selectById(id);
	}

	/**
	 * 保存用户
	 * @param hgoUserInfo
	 * @throws HgoException
	 */
	public void save(HgoUserInfo hgoUserInfo) throws HgoException {
		// 1.0 密码处理
		String encryptPassword = "";	// 加密后的密码
		String password = hgoUserInfo.getPassword();	// 明文密码
		if (StringUtils.isNotBlank(password)) {
			// 校验密码长度
			password = password.replaceAll("\\s*", "");
			if (password.length()<6 || password.length()>16) {
				throw new HgoException(HgoErrorMsg.ERROR_100004);
			}
			// 密码加密
			Md5Hash md5 = new Md5Hash(password);
			encryptPassword = md5.toString();
		}
		
		// 2.0 新增或更新
		if (StringUtils.isEmpty(hgoUserInfo.getId())) {
			// 新增
			int count = iHgoUserInfoDAO.countByLoginName(hgoUserInfo.getLoginName());
			if (count>0) {
				throw new HgoException(HgoErrorMsg.ERROR_100002);
			}
			// 校验密码是否填写
			if ("".equals(encryptPassword)) {
				throw new HgoException(HgoErrorMsg.ERROR_100003);
			}
			
			hgoUserInfo.setId(UUID.randomUUID().toString().replace("-", ""));
			hgoUserInfo.setPassword(encryptPassword);
			hgoUserInfo.setStatus(1);	// 设置正常状态
			
			iHgoUserInfoDAO.insert(hgoUserInfo);
		} else {
			// 更新
			if (!"".equals(encryptPassword)) {
				hgoUserInfo.setPassword(encryptPassword);
			}
			
			iHgoUserInfoDAO.update(hgoUserInfo);
		}
	}

	/**
	 * 删除用户
	 * @param id
	 * @throws HgoException
	 */
	public void deleteById(String id) throws HgoException {
		// 1.0 校验用户是否已分配角色
		List<Integer> roleIdList = iHgoUserRoleDAO.listByUserId(id);
		if (roleIdList!=null && roleIdList.isEmpty()==false) {
			throw new HgoException(HgoErrorMsg.ERROR_100006);
		}
		
		// 2.0 删除用户
		iHgoUserInfoDAO.deleteById(id);
	}

	/**
	 * 用户登录
	 * @param loginName
	 * @param password
	 * @throws HgoException
	 */
	public void login(String loginName, String password) throws HgoException {
		// 获取Subject单例对象
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(loginName, password);
		try {
			// 1.0 登录验证
			subject.login(token);
			
			// 2.0 取出用户信息
			HgoUserInfo hgoUserInfo = (HgoUserInfo)subject.getPrincipal();
			
			// 3.0 设置用户拥有的菜单
			List<HgoMenuInfo> menuList = hgoMenuInfoService.listByUserId(hgoUserInfo.getId());
			if (menuList!=null && menuList.isEmpty()==false) {
				hgoUserInfo.setMenuList(menuList);
			}
			
			// 4.0 设置用户拥有的菜单路径
			List<HgoMenuInfo> userMenuList = iHgoMenuInfoDAO.listByUserId(hgoUserInfo.getId());
			if (userMenuList!=null && userMenuList.isEmpty()==false) {
				Set<String> menuUrlSet = new HashSet<String>();
				for (HgoMenuInfo hgoMenuInfo : userMenuList) {
					if (StringUtils.isNotEmpty(hgoMenuInfo.getUrl())) {
						menuUrlSet.add(hgoMenuInfo.getUrl());
					}
				}
				hgoUserInfo.setMenuUrlSet(menuUrlSet);
			}
			
			// 5.0 设置session
			Session session = subject.getSession();
			session.setAttribute("loginUserInfo", hgoUserInfo);
		} catch (IncorrectCredentialsException ice) {
			// 捕获密码错误异常
			throw new HgoException(HgoErrorMsg.ERROR_100005);
		} catch (UnknownAccountException uae) {
			// 捕获未知用户名异常
			throw new HgoException(HgoErrorMsg.ERROR_100005);
		} catch (LockedAccountException lae) {
			// 账号锁定
			throw new HgoException(HgoErrorMsg.ERROR_100008);
		} catch (ConcurrentAccessException cae) {
			// 一个用户多次登录异常
			throw new HgoException(HgoErrorMsg.ERROR_100009);
		} catch (Exception e) {
			// 未知异常
			throw new HgoException(HgoErrorMsg.ERROR_999999);
		}
	}

	/**
	 * 获取某个角色下的用户列表
	 * @param roleId 角色id
	 * @return
	 */
	public List<HgoUserInfo> listByRoleId(String roleId) {
		return iHgoUserInfoDAO.listByRoleId(roleId);
	}

	/**
	 * 用户自己修改头像或密码
	 * @param hgoUserInfo
	 */
	public void updateByUserSelf(HgoUserInfo hgoUserInfo) {
		iHgoUserInfoDAO.update(hgoUserInfo);
	}

}